//#define CH365DLL64Bit
#define CH365DLLBit
//#define PCI_DEBUG

using System;
using System.Runtime.InteropServices;
//using System.Windows.Forms;


namespace PCICH365
{


    //typedef		VOID	( CALLBACK	* ref mCH365_INT_ROUTINE ) ( VOID );		// 中断服务程序
    unsafe public delegate void mCH365_INT_ROUTINE();


    public class CH365Port
    {

#if CH365DLL64Bit
        const string CH365DLL = "CH365DLL64.dll";
#else
        const string CH365DLL = "CH365DLL.DLL";
#endif


        public enum EnumHardwareRegBit
        {
            // 寄存器的位定义
            mBitAddr15Out = 0x01,		// 设定A15输出值,1*:high,0:low
            mBitSysExtOut = 0x02,		// 设定SYS_EX输出值,1:high,0*:low
            mBitIntAction = 0x04,		// 设定中断激活状态,1:action,0*:inaction
            mBitPciIdDef = 0x01,		// 只读,PCI设备标识的当前选择,1*:default,0:external
            mBitPortHit = 0x04,		// 只读,本地硬件定址功能的启用状态,1:启用,0*:禁用
            mBitInterRom = 0x10,		// 只读,内部Mini-ROM功能的启用状态,1:启用,0*:禁用
            mBitSysExtOe = 0x40,		// 只读,SYS_EX输出三态控制/输出使能,1*:启用,0:禁用
            mBitIntEnable = 0x80,		// 只读,中断功能的启用状态,1:启用,0*:禁用
            mBitI2cStatus = 0x01,		// I2C接口的操作控制和状态,1:开始/正在操作,0*:空闲/操作完成
            mBitI2cSclOut = 0x80,		// 选择I2C接口的SCL输出,1:SYS_EX,0*:A15
            mBitSpeedAct = 0x07,		// 速度控制,激活状态的脉冲宽度,实际宽度为该值乘以30nS
            mBitSpeedInact = 0x10,		// 速度控制,非激活状态的空闲宽度,1:前45nS/后15nS,0:前15nS/后15nS
            mBitSpeedPreft = 0x80,		// 速度控制,预取状态控制位,1:预取位有效,0:预取位无效
        };

        public enum EnumAppLayerFunc
        {
            // 应用层接口的功能代码
            FuncNoOperation = 0x00000000,	// 无操作
            FuncGetVersion = 0x00000001,	// 获取驱动程序版本号
            FuncGetIoBaseAddr = 0x00000004,	// 读取I/O端口基址
            FuncSetIoBaseAddr = 0x00000005,	// 设置I/O端口基址
            FuncGetMemBaseAddr = 0x00000006,	// 读取存储器基址
            FuncSetMemBaseAddr = 0x00000007,	// 设置存储器基址,自动设定存储器基址
            FuncGetInterLine = 0x00000008,	// 读取中断号
            FuncSetInterLine = 0x00000009,	// 设置中断号,自动检测中断号
            FuncWaitInterrupt = 0x0000000a,	// 等待中断,直到CH365产生中断
            FuncAbortWaitInter = 0x0000000b,	// 放弃等待中断,终止等待
            FuncSetExclusive = 0x0000000c,	// 设置独占使用
            FuncReadIoByte = 0x00000010,	// 读取输入输出端口,在同一个端口地址以字节为单位连续读取
            FuncReadIoWord = 0x00000011,	// 读取输入输出端口,在同一个端口地址以字为单位连续读取
            FuncReadIoDword = 0x00000012,	// 读取输入输出端口,在同一个端口地址以双字为单位连续读取
            FuncReadIoBlock = 0x00000013,	// 读取输入输出端口,每读取一个字节,端口地址加一
            FuncWriteIoByte = 0x00000014,	// 写入输入输出端口,在同一个端口地址以字节为单位连续写入
            FuncWriteIoWord = 0x00000015,	// 写入输入输出端口,在同一个端口地址以字为单位连续写入
            FuncWriteIoDword = 0x00000016,	// 写入输入输出端口,在同一个端口地址以双字为单位连续写入
            FuncWriteIoBlock = 0x00000017,	// 写入输入输出端口,每写入一个字节,端口地址加一
            FuncReadMemByte = 0x00000018,	// 读取存储器/寄存器
            FuncReadMemWord = 0x00000019,	// 读取存储器/寄存器
            FuncReadMemDword = 0x0000001a,	// 读取存储器/寄存器
            FuncWriteMemByte = 0x0000001c,	// 写入存储器/寄存器
            FuncWriteMemWord = 0x0000001d,	// 写入存储器/寄存器
            FuncWriteMemDword = 0x0000001e,	// 写入存储器/寄存器
            FuncReadConfig = 0x00000020,	// 读取PCI配置空间
            FuncWriteConfig = 0x00000021,	// 写入PCI配置空间
            FuncReadBuffer1 = 0x00000024,	// 读取中断命令缓冲区1
            FuncWriteBuffer1 = 0x00000025,	// 写入中断命令缓冲区1
            FuncReadBuffer2 = 0x00000026,	// 读取中断命令缓冲区2
            FuncWriteBuffer2 = 0x00000027,	// 写入中断命令缓冲区2
        };


        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct mPCI_CONFIG // 播放文件 
        {
            public ushort mPcVendorId;				    // 00H 供应商标识 
            public ushort mPcDeviceId;					// 02H 设备标识 
            public ushort mPcCommandReg;				// 04H 命令寄存器 
            public ushort mPcStatusReg;					// 06H 状态寄存器 
            public byte mPcRevisionId;				    // 08H 修改标识 
            public byte mPcProgramIf;				    // 09H 寄存器级编程接口 
            public byte mPcSubClass;				    // 0AH 子类代码 
            public byte mPcBaseClass;				    // 0BH 基本分类代码 
            public byte mPcCacheLine;				    // 0CH 缓存行长度 
            public byte mPcLatenTimer;				    // 0DH 延迟计数器 
            public byte mPcHeaderType;				    // 0EH 头标类型 
            public byte mPcBistReg;					    // 0FH 内含自测试寄存器 
            public uint mPcBaseAddr0;					// 10H 基址寄存器0 
            public uint mPcBaseAddr1;					// 14H 基址寄存器1 
            public uint mPcBaseAddr2;					// 18H 基址寄存器2 
            public uint mPcBaseAddr3;					// 1CH 基址寄存器3 
            public uint mPcBaseAddr4;					// 20H 基址寄存器4 
            public uint mPcBaseAddr5;					// 24H 基址寄存器5 
            public uint mPcCardCis;						// 28H 
            public ushort mPcSubSysVen;					// 2CH 子系统供应商标识 
            public ushort mPcSubSysDev;					// 2EH 子系统设备标识 
            public uint mPcExpansRom;					// 30H 扩展ROM基址寄存器 
            public byte mPcCapPtr;					    // 34H
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
            public string mPcReserved1;					// 35H 
            public uint mPcReserved2;					// 38H 
            public byte mPcInterLine;				    // 3CH 中断线寄存器 
            public byte mPcInterPin;				    // 3DH 中断引脚寄存器 
            public byte mPcMinGrant;				    // 3EH 
            public byte mPcMaxLatency;				    // 3FH
        };

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct mPCI_EXP_ROM // PCI扩展ROM的数据结构
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string mPerRomSig;				    // 00H PCI扩展ROM签名字符串'PCIR' 
            public ushort mPerVendorId;				// 04H 供应商标识 
            public ushort mPerDeviceId;				// 06H 设备标识 
            public ushort mPerVpdPtr;					// 08H 重要产品数据指针 
            public ushort mPerStrucLen;				// 0AH PCI扩展ROM数据结构的长度 
            public byte mPerRevision;				// 0CH PCI扩展ROM数据结构的修改版本 
            public byte mPerProgramIf;				// 0DH 寄存器级编程接口 
            public byte mPerSubClass;				// 0EH 子类代码 
            public byte mPerBaseClass;				// 0FH 基本分类代码 
            public ushort mPerImageLen;				// 10H 映像长度 
            public ushort mPerImageRev;				// 12H 映像中代码/数据的修改版本 
            public byte mPerCodeType;				// 14H 代码类型 
            public byte mPerIndicator;				// 15H 映像指示标志 
            public ushort mPerReserved;				// 16H
        } ;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct mCH365_CFG_REG 				// CH365芯片的配置寄存器
        {
            public mPCI_CONFIG mCh365CfgPci;		// 00H-3FH,共64字节为标准PCI配置空间 
            public byte mCh365CfgCtrl;				// 40H 芯片控制寄存器,高5位只读 
            public byte mCh365CfgDin;				// 41H 8位总线输入端口,只读 
            public byte mCh365CfgState;			// 42H 芯片状态寄存器,只读 
            public byte mCh365CfgResv;				// 43H
        } ;


        [StructLayout(LayoutKind.Explicit)]
        public struct mCH365_IO_REG 				        // CH365芯片的I/O空间
        {
            [FieldOffset(0x00)]
            public byte mCh365IoPort;			    // 00H-EFH,共240字节为标准的I/O端口
            [FieldOffset(0xf0)]
            public ushort mCh365MemAddr;			// F0H 存储器接口: A15-A0地址设定寄存器
            [FieldOffset(0xf2)]
            public byte mCh365IoResv2;				// F2H
            [FieldOffset(0xf3)]
            public byte mCh365MemData;				// F3H 存储器接口: 存储器数据存取寄存器
            [FieldOffset(0xf4)]
            public byte mCh365I2cData;				// F4H I2C串行接口: I2C数据存取寄存器
            [FieldOffset(0xf5)]
            public byte mCh365I2cCtrl;				// F5H I2C串行接口: I2C控制和状态寄存器
            [FieldOffset(0xf6)]
            public byte mCh365I2cAddr;				// F6H I2C串行接口: I2C地址设定寄存器
            [FieldOffset(0xf7)]
            public byte mCh365I2cDev;				// F7H I2C串行接口: I2C设备地址和命令寄存器
            [FieldOffset(0xf8)]
            public byte mCh365IoCtrl;				// F8H 芯片控制寄存器,高5位只读
            [FieldOffset(0xf9)]
            public byte mCh365IoBuf;				// F9H 本地数据输入缓存寄存器
            [FieldOffset(0xfa)]
            public byte mCh365Speed;				// FAH 芯片速度控制寄存器
            [FieldOffset(0xfb)]
            public byte mCh365IoResv3;				// FBH
            [FieldOffset(0xfc)]
            public byte mCh365IoTime;				// FCH 硬件循环计数寄存器
            [FieldOffset(0xfd)]
            public byte mCh365IoResv4;			    // FDH
            [FieldOffset(0xfe)]
            public ushort mCh365IoResv5;			// FEH
        };


        public struct mCH365_MEM_REG
        {				// CH365芯片的存储器空间
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x8000)]
            public byte mCh365MemPort;	    // 0000H-7FFFH,共32768字节为标准的存储器单元 
        };


        [StructLayout(LayoutKind.Explicit)]
        public struct mWIN32_COMMAND
        {				// 定义WIN32命令接口结构
            [FieldOffset(0)]
            public uint mFunction;					// 输入时指定功能代码
            [FieldOffset(0)]
            public uint mStatus;					// 输出时返回操作状态
            [FieldOffset(4)]
            public IntPtr mAddress;				// 起始地址,返回地址
            [FieldOffset(8)]
            public uint mLength;					// 存取长度,返回后续数据的长度
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            [FieldOffset(12)]
            public byte mBuffer;					// 数据缓冲区,长度为0至32KB
        };


        [DllImport(CH365DLL)]
        unsafe static extern void* CH365OpenDevice(bool iEnableMemory, bool iEnableInterrupt);// 打开CH365设备,返回句柄,出错则无效, iEnableMemory是否需要支持存储器,iEnableInterrupt是否需要支持中断
        [DllImport(CH365DLL)]
        static extern void CH365CloseDevice();

        // name : CH365DriverCommand
        // return:直接传递命令给驱动程序,出错则返回0,否则返回数据长度
        // input: ref mWIN32_COMMAND ** 命令结构的指针
        // 该程序在调用后返回数据长度,并且仍然返回命令结构,如果是读操作,则数据返回在命令结构中,
        // 返回的数据长度在操作失败时为0,操作成功时为整个命令结构的长度,例如读一个字节,则返回mWIN32_COMMAND_HEAD+1,
        // 命令结构在调用前,分别提供:命令功能代码,起始地址(可选),存取数据的长度(可选),
        // 命令结构在调用后,分别返回:操作状态代码,返回的基址(可选),后续数据的长度(可选),
        //   操作状态代码是由WINDOWS定义的代码,可以参考NTSTATUS.H,
        //   返回的基址只适用于下列命令:获取I/O基址,获取存储器基址,获取中断号,对于其它命令则保持输入时的起始地址
        //   后续数据的长度是指读操作返回的数据长度,数据存放在随后的缓冲区中,对于写操作一般为0
        [DllImport(CH365DLL)]
        static extern UInt32 CH365DriverCommand(ref mWIN32_COMMAND[] ioCommand);
        [DllImport(CH365DLL)]
        static extern UInt32 CH365GetVersion();
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365GetIoBaseAddr(mCH365_IO_REG** oIoBaseAddr);     //获取I/O端口的基址,保存I/O端口基址的单元地址
        [DllImport(CH365DLL)]
        static extern bool CH365SetIoBaseAddr(ref mCH365_IO_REG iIoBaseAddr);        // name : CH365SetIoBaseAddr 设定I/O端口的基址, return:直接传递命令给驱动程序,出错则返回0,否则返回数据长度, input: ref mCH365_IO_REG *  指定I/O端口基址
        [DllImport(CH365DLL)]
        static extern bool CH365GetMemBaseAddr(ref mCH365_MEM_REG[] oMemBaseAddr);   // name : CH365GetMemBaseAddr 获取存储器的基址, input: mCH365_MEM_REG **  保存存储器基址的单元地址
        [DllImport(CH365DLL)]
        static extern bool CH365SetMemBaseAddr(mCH365_MEM_REG iMemBaseAddr);         // name : CH365SetMemBaseAddr 设定存储器的基址, input: mCH365_MEM_REG *    // 指定存储器基址,为0则关闭存储器,为-1则自动设定
        [DllImport(CH365DLL)]
        static extern bool CH365GetIntLine(ref ulong oIntLine);                      // 获取中断号,保存中断号的单元地址
        [DllImport(CH365DLL)]
        static extern bool CH365SetIntLine(ulong iIntLine);                          // 设定中断号,指定中断号,为0则关闭中断,为-1则自动检测并设定
        [DllImport(CH365DLL)]
        static extern bool CH365WaitInterrupt();                                     // 等待中断事件
        [DllImport(CH365DLL)]
        static extern bool CH365AbortWaitInt();                                      // 放弃等待中断
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365SetIntRoutine(ref mCH365_INT_ROUTINE iIntRoutine);            // 设定中断服务程序,指定中断服务程序,为NULL则取消中断服务,否则在中断时调用该程序
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadIntCommand(mWIN32_COMMAND* oCommand, ulong iCmdIndex);     // 读取中断命令缓冲区, 指向一个足够大的缓冲区,用于保存读取的命令结构, 中断命令序号,为1或者2 
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365WriteIntCommand(mWIN32_COMMAND* iCommand, ulong iCmdIndex);   // 写入中断命令缓冲区,指向作为中断命令的命令结构,中断命令序号,为1或者2
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadIoByte(void* iAddr, byte* oByte);                       // 从I/O端口读取一个字节,oByte指向一个字节单元,用于保存读取的字节数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadIoWord(void* Addr, ushort* oWord);                       // 从I/O端口读取一个字,iAddr指定I/O端口的地址,oWord指向一个字单元,用于保存读取的字数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadIoDword(void* iAddr, ulong* oDword);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365WriteIoByte(void* iAddr, byte iByte);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365WriteIoWord(void* iAddr, ushort iWord);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365WriteIoDword(void* iAddr, ulong iDword);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadMemByte(void* iAddr, byte* oByte);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadMemDword(void* iAddr, ulong* oDword);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365WriteMemByte(void* iAddr, byte iByte);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365WriteMemDword(void* iAddr, ulong iDword);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadConfig(void* iOffset, byte* oByte);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365WriteConfig(void* iOffset, byte iByte);
        [DllImport(CH365DLL)]
        static extern bool CH365SetA15_A8(byte iA15_A8);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365ReadI2C(byte iDevice, byte iAddr, byte* oByte);
        [DllImport(CH365DLL)]
        static extern bool CH365WriteI2C(byte iDevice, byte iAddr, byte iByte);
        [DllImport(CH365DLL)]
        unsafe static extern void* CH365mOpenDevice(ushort iIndex, bool iEnableMemory, bool iEnableInterrupt);
        [DllImport(CH365DLL)]
        unsafe static extern void* CH365mCloseDevice(ushort iIndex);
        [DllImport(CH365DLL)]
        unsafe static extern ulong CH365mDriverCommand(ushort iIndex, mWIN32_COMMAND* ioCommand);        // 直接传递命令给驱动程序,出错则返回0,否则返回数据长度,iIndex指定CH365设备序号,ioCommand命令结构的指针
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mGetIoBaseAddr(ushort iIndex, mCH365_IO_REG** oIoBaseAddr);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mSetIoBaseAddr(ulong iIndex, mCH365_IO_REG* iIoBaseAddr);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mGetMemBaseAddr(ushort iIndex, mCH365_MEM_REG** oMemBaseAddr);
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mSetMemBaseAddr(ushort iIndex, mCH365_MEM_REG* iMemBaseAddr);     // 指定存储器基址,为0则关闭存储器,为-1则自动设定
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mGetIntLine(ulong iIndex, ulong* oIntLine);  	                    // 保存中断号的单元地址
        [DllImport(CH365DLL)]
        static extern bool CH365mSetIntLine(ushort iIndex, ulong iIntLine);  			                    // 指定中断号,为0则关闭中断,为-1则自动检测并设定
        [DllImport(CH365DLL)]
        static extern bool CH365mWaitInterrupt(ushort iIndex);  						                    // 指定CH365设备序号
        [DllImport(CH365DLL)]
        static extern bool CH365mAbortWaitInt(ushort iIndex);  						                    // 指定CH365设备序号
        [DllImport(CH365DLL)]
        static extern bool CH365mSetIntRoutine(ushort iIndex, ref mCH365_INT_ROUTINE iIntRoutine);        // 指定中断服务程序,为NULL则取消中断服务,否则在中断时调用该程序
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadIntCommand(ushort iIndex, mWIN32_COMMAND* oCommand, ulong iCmdIndex);     // 中断命令序号,为1或者2
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mWriteIntCommand(ushort iIndex, mWIN32_COMMAND* iCommand, ulong iCmdIndex);    // 中断命令序号,为1或者2
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadIoByte(ushort iIndex, void* iAddr, byte* oByte);            // 指向一个字节单元,用于保存读取的字节数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadIoWord(ushort iIndex, void* iAddr, ushort* oWord);           // 指向一个字单元,用于保存读取的字数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadIoDword(ushort iIndex, void* iAddr, ulong* oDword);          // 指向一个双字单元,用于保存读取的双字数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mWriteIoByte(ushort iIndex, void* iAddr, byte iByte);             // 待写入的字节数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mWriteIoWord(ushort iIndex, void* iAddr, ushort iWord);           // 待写入的字数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mWriteIoDword(ushort iIndex, void* iAddr, ulong iDword);          // 待写入的双字数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadMemByte(ulong iIndex, void* iAddr, byte* oByte);           // 指向一个字节单元,用于保存读取的字节数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadMemDword(ulong iIndex, void* iAddr, ulong* oDword);         // 指向一个双字单元,用于保存读取的双字数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mWriteMemByte(ulong iIndex, void* iAddr, byte iByte);            // 待写入的字节数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mWriteMemDword(ulong iIndex, void* iAddr, ulong iDword);         // 待写入的双字数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadConfig(long iIndex, void* iOffset, byte* oByte);           // 指向一个字节单元,用于保存读取的字节数据
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mWriteConfig(ulong iIndex, void* iOffset, byte iByte);           // 待写入的字节数据
        [DllImport(CH365DLL)]
        static extern bool CH365mSetA15_A8(ulong iIndex, byte iA15_A8);                                  // 位7-位0对应A15-A8的输出,1为高电平,0为低电平
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mReadI2C(ulong iIndex, byte iDevice, byte iAddr, byte* oByte);   // 指向一个字节单元,用于保存读取的字节数据
        [DllImport(CH365DLL)]
        static extern bool CH365mWriteI2C(ulong iIndex, byte iDevice, byte iAddr, byte iByte);           // 待写入的字节数据
        [DllImport(CH365DLL)]
        static extern bool CH365DelayUS(ulong iDelay);                                                   // 指定要延时的微秒数,如果延时小于10则误差较大
        [DllImport(CH365DLL)]
        unsafe static extern bool CH365mAccessBlock(ulong iIndex, ulong iAccessMode, void* iAddr, void* ioBuffer, ulong iLength);
        [DllImport(CH365DLL)]
        static extern bool CH365mSetExclusive(ulong iIndex, ulong iExclusive);


        static IntPtr[] HandPCICH365 = new IntPtr[4];//IntPtr.Zero;
        static unsafe void* IoBaseAddr = null;

        unsafe public static void* GetIOBaseAddr(int index)
        {
            if (((byte*)IoBaseAddr != (byte*)0) && ((byte*)IoBaseAddr != (byte*)0xffffffff))
                return (void*)((byte*)IoBaseAddr/*.ToPointer()*/ + index);
            else
                return (void*)0;
        }

        unsafe static bool ReadIoByte(int iAddr, ref byte oByte)
        {
            byte v = 0;
            if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            bool ret = CH365ReadIoByte(GetIOBaseAddr(iAddr), &v);
            oByte = v;
            return ret;
        }

        public unsafe bool ReadIoWord(int iAddr, ref ushort oWord)
        {
            ushort v = 0;
            /*if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            bool ret = CH365ReadIoWord(GetIOBaseAddr(iAddr), &v);*/
            bool ret = CH365ReadIoWord((void*)iAddr, &v);
            oWord = v;
            return ret;
        }
        public unsafe bool mReadIoWord(ushort iIndex, int iAddr, ref ushort oWord)
        {
            ushort v = 0;
            /*if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            bool ret = CH365ReadIoWord(GetIOBaseAddr(iAddr), &v);*/
            bool ret = CH365mReadIoWord(iIndex,(void*)iAddr, &v);
            oWord = v;
            return ret;
        }

        unsafe static bool ReadIoDword(int iAddr, ref ulong oDword)
        {
            ulong v = 0;
            if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            bool ret = CH365ReadIoDword(GetIOBaseAddr(iAddr), &v);
            oDword = v;
            return ret;
        }

        unsafe static bool WriteIoByte(int iAddr, byte iByte)
        {
            if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            else
                return CH365WriteIoByte(GetIOBaseAddr(iAddr), iByte);
        }

        public unsafe bool WriteIoWord(int iAddr, ushort iWord)
        {/*
            if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            else
                return CH365WriteIoWord(GetIOBaseAddr(iAddr), iWord);*/
            return CH365WriteIoWord((void*)iAddr, iWord);

        }

        public unsafe bool mWriteIoWord(ushort iIndex, int iAddr, ushort iWord)
        {/*
            if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            else
                return CH365WriteIoWord(GetIOBaseAddr(iAddr), iWord);*/
            return CH365mWriteIoWord(iIndex,(void*)iAddr, iWord);

        }
        unsafe static bool WriteIoDword(int iAddr, ulong iDword)
        {
            if (GetIOBaseAddr(iAddr) == (void*)0)
                return false;
            else
                return CH365WriteIoDword(GetIOBaseAddr(iAddr), iDword);
        }

        public unsafe bool Open(ushort iIndex)
        {
#if PCI_DEBUG
            return true;
#else

            HandPCICH365[iIndex] = IntPtr.Zero;
            void* Hand = CH365mOpenDevice(iIndex,false, false);
                // Handle exception
                if (Hand == (void*)0xffffffff)
                {
                    return false;
                }

               HandPCICH365[iIndex] = (IntPtr)Hand;

                //add for adc1-adc4 calibrating by wangliang 2016-6-22
                mWriteIoWord(iIndex, 0x0c, 1);//RESET ADC 
                mWriteIoWord(iIndex, 0x0c, 0);//RESET ADC
                mWriteIoWord(iIndex, 0x34, 3);//MANUAL MODE
                mWriteIoWord(iIndex, 0x48, 100);//ADC INTEG//mWriteIoWord(iIndex, 0x48, 0x12c);//ADC INTEG
                mWriteIoWord(iIndex, 0x46, 0); //bypass ave


                //end
                mWriteIoWord(iIndex, 0x36, 0);//关闭继电器输出
                mWriteIoWord(iIndex, 0x12, (ushort)(9*65535/30.0));//输出极限电压20V
                mWriteIoWord(iIndex, 0xE0, 10);
                mWriteIoWord(iIndex, 0xE2,3);
                mWriteIoWord(iIndex, 0xE4, 2);
                mWriteIoWord(iIndex, 0xE6, 5);
                mWriteIoWord(iIndex, 0xE8, 0);
                
                return true;
            

#endif
        }

        // Constructor
        public CH365Port()
        {
            //Open();
        }

        ~CH365Port()
        {
            //Close();
            for (ushort i = 0; i < 4; i++)
            {
                Close(i);
            }
        }

        public bool Init(ushort i)
        {
            return Open(i);
        }

        public unsafe void Close(ushort i)
        {
            if (HandPCICH365[i] != IntPtr.Zero)
            {
                mWriteIoWord(i, 0x34, 2);//MANUAL MODE
                CH365mCloseDevice(i);
                HandPCICH365[i] = IntPtr.Zero;
            }
        }

    }
}
